package model;

import java.io.*;
import java.util.logging.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * Класс, реализующий методы сохранения/загрузки объектов в XML
 * @version 1.0
 * @see Model
 * @see DataLoadable
 */
public class ProcessXMLData {

     /**
     * Метод загружает объект из XML-файла
     * @param fileName Имя файла
     * @param c Класс загружаемого объекта
     * @return DataLoadable Объект
     */   
    public static DataLoadable loadData(String fileName, Class c) {
        try {
            JAXBContext jc = JAXBContext.newInstance(c);
            Unmarshaller u = jc.createUnmarshaller();
            //FileInputStream fIn = new FileInputStream(fileName);
            //GZIPInputStream f = new GZIPInputStream(fIn);
            File f = new File(fileName);
            DataLoadable all = null;
            //if (f != null && f.available() != 0) {
            
            if(f.isFile()){
                all = (DataLoadable) u.unmarshal(f);
            }
            //fIn.close();
            //f.close();
            return all;
        } catch (Exception ex) {
            Logger.getLogger(DataLoadable.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

     /**
     * Метод сохраняет объект в XML-файл
     * @param fileName Имя файла
     * @param data Объект
     * @param overwrite Приоритет при обновлении объектов
     */   
    public static void saveData(String fileName, DataLoadable data, boolean overwrite) {
        try {
            JAXBContext context = JAXBContext.newInstance(data.getClass());
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            DataLoadable serverdata = ProcessXMLData.loadData(fileName, data.getClass());
            if (serverdata != null) {
                for (int i = 0; i < serverdata.getSize(); i++) {
                    if (data.contains(serverdata.getElementByID(i))) {
                        if (!overwrite) {
                            data.update(serverdata.getElementByID(i));
                        }
                    } else {
                        //data.add(serverdata.getElementByID(i));
                    }
                }
            }
            FileOutputStream f = new FileOutputStream(fileName);
            //GZIPOutputStream f = new GZIPOutputStream(f1);
            m.marshal(data, f);
            //f1.flush();
            f.flush();
            //f1.close();            
            f.close();
        } catch (Exception ex) {
            Logger.getLogger(DataLoadable.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

       /**
     * Метод загружает объект из XML-строки
     * @param fileName Имя файла
     * @param c Класс загружаемого объекта
     * @return DataLoadable Объект
     */   
    public static DataLoadable loadDataFromXML(String xml, Class c) {
        try {
            JAXBContext jc = JAXBContext.newInstance(c);
            Unmarshaller u = jc.createUnmarshaller();
            DataLoadable data = (DataLoadable) u.unmarshal(new ByteArrayInputStream(xml.getBytes()));
            return data;
        } catch (Exception ex) {
            Logger.getLogger(DataLoadable.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
  
    /**
     * Метод сохраняет объект в строку
     * @param fileName Имя файла
     * @param data Объект
     * @param overwrite Приоритет при обновлении объектов
     * @return String XML строка
     */      
    public static String saveDataToXML(DataLoadable data) {
        try {
            JAXBContext context = JAXBContext.newInstance(data.getClass());
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            ByteArrayOutputStream bao = new ByteArrayOutputStream();
            m.marshal(data, bao);
            return bao.toString();
        } catch (Exception ex) {
            Logger.getLogger(DataLoadable.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

}
